package com.rrd.hive.udf;

import com.weicai.caesar.CaesarUtil;
import com.rrd.hive.util.PIDValidator;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;


@Description(
        name = "pid_age",
        value = "_FUNC_(pid, mode) - Get age from pid or caesar encode pid",
        extended = "Example:\n> SELECT _FUNC_('110106201012310313');\n  10\n> SELECT _FUNC_('110106201012310313','exactly');\n  11"
)
public class PidAgeUDF extends UDF {

    public Text evaluate(String pid) {
        return evaluate(pid, "normal");
    }

    public Text evaluate(String pid, String mode) {
        if (pid == null || pid.equals("")) {
            return null;
        }
        Text res = new Text();
        if (CaesarUtil.isEncrypted(pid)) {
            pid = CaesarUtil.decode(pid);
        }
        if (pid.length() != 18 || !PIDValidator.isValidIDCard(pid)) {
            return null;
        }

        String birthday = pid.substring(6, 14);
        int age = this.getAge(this.parse(birthday), mode);
        if (age <= 0) {
            return null;
        }
        res.set(String.valueOf(age));
        return res;
    }

    public Date parse(String strDate) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        try {
            return sdf.parse(strDate);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    //由出生日期获得年龄
    public int getAge(Date birthDay, String mode) {
        Calendar cal = Calendar.getInstance();

        if (birthDay == null || cal.before(birthDay)) {
            return 0;
        }
        int yearNow = cal.get(Calendar.YEAR);
        int monthNow = cal.get(Calendar.MONTH);
        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birthDay);

        int yearBirth = cal.get(Calendar.YEAR);
        int monthBirth = cal.get(Calendar.MONTH);
        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

        int age = yearNow - yearBirth;
        if (mode.equals("exactly")) {
            if (monthNow <= monthBirth) {
                if (monthNow == monthBirth) {
                    if (dayOfMonthNow < dayOfMonthBirth) {
                        age--;
                    }
                } else {
                    age--;
                }
            }
        }
        return age;
    }

    public static void main(String[] args) {
        PidAgeUDF dfu = new PidAgeUDF();
        System.out.println(dfu.evaluate(CaesarUtil.encode("110106198705170313"), "exactly"));
    }
}
